Reports - Custom Data Sources

Description

When you create Report in Alpha Anywhere you could choose to base the report on a SQL data source, a native .dbf table, or a Custom data source. .

images/report_custom1.jpg
When creating 'Project reports' (Reports defined in the Web Projects Control Panel), the option to base the report on a .dbf table is not available.

When you specify a custom data source the following dialog appears:

images/reports_custom2.jpg

You specify the name of an Xbasic function that will return the data to be printed by the report.

The Xbasic function can return data in one of two formats:

  • Delimited
  • JSON

In both list, the Xbasic function returns a string of data (that is either in delimited or JSON format - explained below).

The function prototype for the Xbasic function is (assuming you specified that the Function name was myDataFunction in the Function name property in image shown above):

function myDataFunction as c (e as p)
myDataFunction = <<%txt%
......the delimited, or JSON format data goes here
%txt%

end function

Notice that the function takes a single input parameter, e.

The e object that is passed into the function includes the value of any arguments that were passed into the report.

For example, assume that you specified that the Custom Data Source uses an argument called whatCountry. Your Xbasic function can reference the value in this argument as follows:

dim country as c 
country = argVal(e.arguments,"whatCountry")

Understanding the Format of the Delimited Data Your Custom Function Must Return

The delimited option allows you to return a CR-LF delimited list of data. Each row in the data that are returned represents a row of data in your report. The 'fields' in the data are typically delimited with a pipe character (e.g. |), but you are free to specify any delimiter. For example, here is how a simple Xbasic function could be defined to return some data for a report.

function myXBfunction as c (e as p)

dim txt as c 
txt = <<%txt%
Firstname|Lastname|City
Fred|Smith|Boston
John|Jones|London
%txt%
myXBfunction = txt

end function

Notice that the first row of data in the string that is returned by the function are the field names. In this example, the field names are Firstname, LastName and City.

The first row of data can optionally include additional information that defines the data type and size of each field.

For example:

function myXBfunction as c (e as p)

dim txt as c 
txt = <<%txt%
Firstname=C20|Lastname=C30|City=C20|DOB=D|Salary=10.2
Fred|Smith|Boston|12/6/1972|86500.00
John|Jones|London|11/5/1982|76000.00
%txt%

myXBfunction = txt
end function

For Character fields, the format is defined as Cw where 'w' is the size of the field. For Numeric fields, the format is defined as Nw.d where 'w' is the size of the field and 'd' is the number of decimal places.

The following field type codes can be used:

C

Character

N

Numeric

L

Logical

M

Memo

D

Date

T

Date/time

S

Short time (time portion of a data/time field only)

E

Exponent numeric

K

Guid

Understanding the Format of the JSON Data Your Custom Function Must Return

The JSON data that your function returns can be Simple or Complex.

Simple JSON

For Simple JSON, the string that you return is just an array of JSON objects, For example:

function myjson as c(e as p)
myjson = <<%json%
[
    {"Firstname" : "Fred", "Lastname" : "Smith"},
    {"Firstname" : "Harry", "Lastname" : "Jones"}
]
%json%
end function

In this item since no schema is supplied the data are all considered to be character type of length 1024 characters. While the advantage of this format is that is extremely simple, it does mean that you will need to adjust the size of each field you place on your report because its default size will likely be too large.

Complex JSON

For Complex JSON, the string that you return is an object with two properties, schema and data. The schema object defines the schema of the data (for example, field type, size, etc.) and the data property is an array of JSON objects that define the data for the report. For example:

function myjson as c(e as p)
myjson = <<%json%
{
    "schema" : { "firstname" : { "type" : "C" , "width": 30 } 
               , "lastname" : { "type" : "C" , "width": 30} 
               , "company" : { "type" : "C" , "width": 30} 
               , "age" : { "type" : "N" , "width" : 3, "decimal" : 0 }
    },
    "data":
            [
                {"firstname":"Fred", "lastname":"Smith", "company" : "Alpha Software", "age" : 30},
                {"firstname":"John", "lastname":"Jones", "company" : "Beta Software", "age" : 23}
            ]
}
%json%
end function

In the above example, we have specified the size and type of each field in the data array. Notice that we have also specified the number of decimal places for the numeric field.

The data types supported in the schema are:

C

Character (you must also specify a "width" property for this type)

N

Numeric (you must also specify a "width" and "decimal" property for this type)

L

Logical

M

Memo

D

Date

T

Date/time

Y

Short time

E

Exponent numeric

K

Guid

JPEG

Jpeg field (data in the JSON data property is expected to be base64 encoded)

PNG

PNG (data in the JSON data property is expected to be base64 encoded)

BMP

BMP (data in the JSON data property is expected to be base64 encoded)

I

Image Reference Field (data in the data property is a image file name but the report will treat the data as an image).

If you specify that a field uses the Date (D), Date/Time (T) or Short time (Y) format in the schema, the data in the data array must be a string in UTC date format. For example: 2014-10-27T23:06:50.361Z. The date part format is yyyy-mm-dd and the time part uses GMT. In the item of a Short time field, the date portion of the UTC date string is ignored.

The schema also allows you to extract data from objects within each row and to map property names in the data array to different names. For example in the data shown below, the address property is an object with two sub-properties.

{
    "name": "Fred Smith",
    "company" : "XYZ Corp",
    "address": {
        "street": "Main Street",
        "number": 23
    }
}

Shown below is how the function would be defined to return the JSON data. Notice that the JSON object has both a schema and a data property. The schema indicates what fields will be available to the report. The list of fields specified by the schema are: name, companyName, street and number.

Notice that the data array does not have a property called companyName. It has a property called company. So the schema property for the companyName field indicates that the source of this field is the company property in the data array. Similarly, the street field in the schema is mapped to the address.street property in the data array.

If the definition for a field in the schema omits the source property, then the source is the same as the item name. For example the definition for the name field in the schema shown below does not have a source property, therefore this field is mapped to the name property in the data array.

function myjson as c(e as p)
myjson = <<%json%
{
    "schema": {
        "name": {
            "type": "c",
            "width": 30
        },
        "companyName: {
        	"source": "company",
        	"type" : "c",
        	"width" : 30
        },
        
        "street": {
            "source": "address.street",
            "type": "c",
            "width": 40
        },
        "number": {
            "source": "address.number",
            "type": "n",
            "width": 5,
            "decimal": 0
        }
    },
    "data": [
        {
            "name": "Fred Smith",
            "company" : "XYZ Corp",
            "address": {
                "street": "Main Street",
                "number": 23
            }
        },
        {
            "name": "John Jones",
            "company" : "ABC Corp",
            "address": {
                "street": "Corner Road",
                "number": 3
            }
        }
    ]
}
%json%
end function

In the next example, we show how the JSON object that you specify can include image data. The binary data for the image are encoded as base64 strings. The example shows the complete function definition. Notice that the schema indicates that the image field will be stored as a PNG. Notice also that in the first record, the base64 encoded data in the image property does not include the MIME type at the start of the base64 encoded data. This data is therefore presumed to be a PNG image since the schema indicates that the image is a PNG type. Notice however, that the second row of data in the data array has a MIME type prefix on the base64 encoded image data. The data for the image is for a BMP image. The image will therefore be converted from BMP to PNG automatically.

function myjson as c(e as p)
myjson = <<%json%
{
   "schema" : {
      "name" : { "type" : "C" , "width": 30 }, 
      "image" : { "type" : "Png" }
    },
    "data": 
       [
          {"name":"John Smith", "image" : "iVBORw...(data truncated for readability)....AAAElFTkSuQmCC" },
          {"name":"Jane Smith", "image" : "data:image/bmp;base64,Qk02AwAAA...(data truncated for readability)....AAAADYAAAAAA=="}
       ]
}
%json%
end function

See Also